﻿Public Class Line
#Region "属性"
    Dim mText As String
    ''' <summary>
    ''' 行的文本
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Text() As String
        Get
            Return mText
        End Get
        Set(ByVal value As String)
            mText = value
            InitLine()
        End Set
    End Property
    Dim mHasSelection As Boolean
    ''' <summary>
    ''' 该行是否存在被选中的文本
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property HasSelection() As Boolean
        Get
            Return mHasSelection
        End Get
        Set(ByVal value As Boolean)
            mHasSelection = value
        End Set
    End Property
    ''' <summary>
    ''' 该行的选中文字
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property Selection() As String
        Get
            If HasSelection Then
                Return Mid(Text, SelectStart, SelectLength)
            Else
                Return String.Empty
            End If
        End Get
    End Property
    ''' <summary>
    ''' 是否整行被选中
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property IsWholeSelected() As Boolean
        Get
            If mHasSelection And (SelectStart = 1 And SelectLength = Text.Length) Then
                Return True
            Else
                Return False
            End If
        End Get
    End Property
    Dim mHasHeightLightWord As Boolean
    ''' <summary>
    ''' 该行是否存在关键字
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property HasHeightLightWord() As Boolean
        Get
            Return mHasHeightLightWord
        End Get
    End Property
    Dim mHeightLightWord As String
    ''' <summary>
    ''' 检索关键字
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property HeightLightWord() As String
        Get
            Return mHeightLightWord
        End Get
    End Property
    Dim mHasSearchWord As Boolean
    ''' <summary>
    ''' 该行是否存在检索关键字
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property HasSearchWord() As Boolean
        Get
            Return mHasSearchWord
        End Get
    End Property
    Dim mSelectStart As Integer
    ''' <summary>
    ''' 选中开始位置
    ''' </summary>
    ''' <remarks></remarks>
    Property SelectStart() As Integer
        Get
            Return mSelectStart
        End Get
        Set(ByVal value As Integer)
            mSelectStart = value
        End Set
    End Property
    Dim mSelectLength As Integer
    ''' <summary>
    ''' 选中长度
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property SelectLength() As Integer
        Get
            Return mSelectLength
        End Get
        Set(ByVal value As Integer)
            mSelectLength = value
        End Set
    End Property
    Dim mWidth As Integer
    ''' <summary>
    ''' 文本宽度，如果是等宽字体的话，不需要这个属性，如果是非等宽字体的话，这个属性必须
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ReadOnly Property Width()
        Get
            Return mWidth
        End Get
    End Property
#End Region
#Region "内部方法"
    ''' <summary>
    ''' 行里的单词
    ''' </summary>
    ''' <remarks></remarks>
    Structure struWord
        Dim StartPos As Integer
        Dim Length As Integer
    End Structure
    Public WordList As New List(Of struWord)
    Sub New()
        mText = String.Empty
    End Sub
    Sub New(ByVal strText As String)
        mText = strText
        InitLine()
    End Sub
    Friend Sub InitLine()
        'Tab的替换
        If TabSpace > 0 Then mText = mText.Replace(Chr(9), Space(TabSpace))
        '宽度的变换
        ReSetWidth()
        '重新分词
        RefreshWordList()
        '高亮关键字
        ResetHeightLightWord(mHeightLightWord)
    End Sub
    Friend Sub RefreshWordList()
        Dim IsInWatch As Boolean
        Dim WordStart As Integer
        Dim WordLength As Integer
        WordList.Clear()
        Dim ShadowText As String
        ShadowText = mText
        If mText = "" Then Exit Sub
        If DelimitMark.Count > 1 Then
            For i As Byte = 0 To DelimitMark.Count - 1
                ShadowText = ShadowText.Replace(DelimitMark(i), Space(1))
            Next
        End If
        For i As Integer = 1 To ShadowText.Length
            If Mid(ShadowText, i, 1) <> Space(1) Then
                If IsInWatch Then
                    WordLength += 1
                Else
                    IsInWatch = True
                    WordLength = 1
                    WordStart = i
                End If
            Else
                If IsInWatch Then
                    Dim mWord As New struWord
                    mWord.StartPos = WordStart
                    mWord.Length = WordLength
                    WordList.Add(mWord)
                    IsInWatch = False
                    WordLength = 0
                End If
            End If
        Next
        If IsInWatch Then
            Dim mWord As New struWord
            mWord.StartPos = WordStart
            mWord.Length = WordLength
            WordList.Add(mWord)
        End If
    End Sub
    ''' <summary>
    ''' 重新取得行宽
    ''' </summary>
    ''' <remarks></remarks>
    Sub ReSetWidth()
        mWidth = MeasureTextWidth(mText)
    End Sub
#End Region
#Region "查找和替换"
    ''' <summary>
    ''' 根据关键字重置是否有高亮关键字标志
    ''' </summary>
    ''' <param name="strKeyWord"></param>
    ''' <remarks></remarks>
    Friend Sub ResetHeightLightWord(ByVal strKeyWord As String)
        mHasHeightLightWord = False
        mHeightLightWord = strKeyWord
        If strKeyWord = String.Empty Then
            Exit Sub
        End If
        For i = 0 To WordList.Count - 1
            If UCase(Mid(Me.Text, WordList(i).StartPos, WordList(i).Length)) = UCase(strKeyWord) Then
                mHasHeightLightWord = True
                Exit For
            End If
        Next
    End Sub
    ''' <summary>
    ''' 根据关键字重置是否有检索关键字标志
    ''' </summary>
    ''' <param name="strKeyWord"></param>
    ''' <remarks></remarks>
    Friend Sub ResetSearchKeyWord(ByVal strKeyWord As String)
        mHasSearchWord = False
        If strKeyWord = String.Empty Then Exit Sub
        For i = 0 To WordList.Count - 1
            If UCase(Mid(Me.Text, WordList(i).StartPos, WordList(i).Length)) = UCase(strKeyWord) Then
                mHasSearchWord = True
                Exit For
            End If
        Next
    End Sub
    ''' <summary>
    ''' 整行文本替换
    ''' </summary>
    ''' <param name="oldString">旧字符</param>
    ''' <param name="newString">新字符</param>
    ''' <remarks></remarks>
    Friend Sub Replace(ByVal oldString As String, ByVal newString As String)
        If Me.Text <> "" Then Me.Text = Me.Text.Replace(oldString, newString)
    End Sub
#End Region
#Region "文本选择"
    ''' <summary>
    ''' 选中文本
    ''' </summary>
    ''' <param name="SelStart">起始位置</param>
    ''' <param name="SelLength">长度</param>
    ''' <remarks></remarks>
    Sub atomic_SelectText(ByVal SelStart As Integer, ByVal SelLength As Integer)
        mSelectStart = SelStart
        mSelectLength = SelLength
        mHasSelection = False
        If mSelectLength > 0 Then mHasSelection = True
    End Sub
    ''' <summary>
    ''' 从行首到指定位置为选中位置
    ''' </summary>
    ''' <param name="CurrentXPos">指定位置</param>
    ''' <remarks>从1开始</remarks>
    Friend Sub atomic_SelectToHeader(ByVal CurrentXPos As Integer)
        mHasSelection = True
        mSelectStart = 1
        mSelectLength = CurrentXPos - 1
    End Sub
    ''' <summary>
    ''' 从指定位置选中到行尾
    ''' </summary>
    ''' <param name="CurrentXPos">指定位置</param>
    ''' <remarks></remarks>
    Friend Sub atomic_SelectToEnd(ByVal CurrentXPos As Integer)
        mHasSelection = True
        mSelectStart = CurrentXPos
        mSelectLength = mText.Length - CurrentXPos + 1
    End Sub
    ''' <summary>
    ''' 选中整行
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub atomic_SelectAll()
        mHasSelection = True
        mSelectStart = 1
        mSelectLength = mText.Length
    End Sub
    ''' <summary>
    ''' 取消选中
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub atomic_UnSelectAll()
        If mHasSelection = False Then Exit Sub
        mHasSelection = False
        mSelectStart = 0
        mSelectLength = 0
    End Sub
#End Region
#Region "显示属性"
    Dim mIsFirstLine As Boolean
    ''' <summary>
    ''' 折行显示的时候，是否为首行
    ''' </summary>
    ''' <remarks></remarks>
    Property Dis_IsFirstLine() As Boolean
        Get
            Return mIsFirstLine
        End Get
        Set(ByVal value As Boolean)
            mIsFirstLine = value
        End Set
    End Property
    Dim mIsLastLine As Boolean
    ''' <summary>
    ''' 折行显示的时候，是否为末行
    ''' </summary>
    ''' <remarks></remarks>
    Property Dis_IsLastLine() As Boolean
        Get
            Return mIsLastLine
        End Get
        Set(ByVal value As Boolean)
            mIsLastLine = value
        End Set
    End Property
    Dim mTotalCount As Integer
    ''' <summary>
    ''' 折行显示的时候指示这个行一共被分为了几个子行
    ''' </summary>
    ''' <remarks></remarks>
    Property Dis_TotalCount() As Integer
        Get
            Return mTotalCount
        End Get
        Set(ByVal value As Integer)
            mTotalCount = value
        End Set
    End Property
    Dim mCurrentLineNo As Integer
    ''' <summary>
    ''' 折行显示的时候指示这个行在整个子行里的位置
    ''' </summary>
    ''' <remarks></remarks>
    Property Dis_CurrentLineNo() As Integer
        Get
            Return mCurrentLineNo
        End Get
        Set(ByVal value As Integer)
            mCurrentLineNo = value
        End Set
    End Property
    Dim mRealLineNumber As Integer
    ''' <summary>
    ''' 真实行号
    ''' </summary>
    ''' <remarks></remarks>
    Property Dis_RealLineNumber() As Integer
        Get
            Return mRealLineNumber
        End Get
        Set(ByVal value As Integer)
            mRealLineNumber = value
        End Set
    End Property
    Dim mIsPartyOfComment As Boolean
    ''' <summary>
    ''' 是否为注释块的一部分
    ''' </summary>
    ''' <remarks>当折行显示的时候，可能注释符号在上面一行，
    ''' 这个虽然没有注释符号，但也必须被注释</remarks>
    Property Dis_IsPartyOfComment() As Boolean
        Get
            Return mIsPartyOfComment
        End Get
        Set(ByVal value As Boolean)
            mIsPartyOfComment = value
        End Set
    End Property
    Enum CodeFoldType As Byte
        None
        Header
        Footer
        Whole
    End Enum
    Dim mCodeFold As CodeFoldType
    ''' <summary>
    ''' 代码折叠时候的贯穿线样式
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Dis_CodeFold() As CodeFoldType
        Get
            Return mCodeFold
        End Get
        Set(ByVal value As CodeFoldType)
            mCodeFold = value
        End Set
    End Property
#End Region
#Region "真实行属性"
    Dim mMemoryStartLineNo As Integer
    ''' <summary>
    ''' 内存开始行号
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_MemoryStartLineNo() As Integer
        Get
            Return mMemoryStartLineNo
        End Get
        Set(ByVal value As Integer)
            mMemoryStartLineNo = value
        End Set
    End Property
    Dim mMemoryEndLineNo As Integer
    ''' <summary>
    ''' 内存结束行号
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_MemoryEndLineNo() As Integer
        Get
            Return mMemoryEndLineNo
        End Get
        Set(ByVal value As Integer)
            mMemoryEndLineNo = value
        End Set
    End Property
    Dim mIsBlockHeader As Boolean
    ''' <summary>
    ''' 是否为代码折叠的首行
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsBlockHeader() As Boolean
        Get
            Return mIsBlockHeader
        End Get
        Set(ByVal value As Boolean)
            mIsBlockHeader = value
        End Set
    End Property
    Dim mBlockLV As Byte
    ''' <summary>
    ''' 代码折叠的等级
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_BlockLV() As Byte
        Get
            Return mBlockLV
        End Get
        Set(ByVal value As Byte)
            mBlockLV = value
        End Set
    End Property
    Dim mIsBlockNeedFooter As Boolean
    ''' <summary>
    ''' 是否需要段落结束标志
    ''' COBOL语言的SECTION，特殊DIVISION没有结束标志
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Real_IsBlockNeedFooter() As Boolean
        Get
            Return mIsBlockNeedFooter
        End Get
        Set(ByVal value As Boolean)
            mIsBlockNeedFooter = value
        End Set
    End Property
    Dim mIsBlockFooter As Boolean
    ''' <summary>
    ''' 是否为代码折叠的尾行
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsBlockFooter() As Boolean
        Get
            Return mIsBlockFooter
        End Get
        Set(ByVal value As Boolean)
            mIsBlockFooter = value
        End Set
    End Property
    Dim mBlockKeyWord As New List(Of String)
    ''' <summary>
    ''' 代码折叠的关键字
    ''' </summary>
    ''' <remarks>可能是多个关键字的尾行
    '''          例如在COBOL的时候，一行可以使SECTION的最后一行，也可以是DIVISION的最后一行
    ''' </remarks>
    Property Real_BlockKeyWord() As List(Of String)
        Get
            Return mBlockKeyWord
        End Get
        Set(ByVal value As List(Of String))
            mBlockKeyWord = value
        End Set
    End Property
    Dim mCanBeFolder As Boolean
    ''' <summary>
    ''' 代码是否能够被折叠
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_CanBeFolder() As Boolean
        Get
            Return mCanBeFolder
        End Get
        Set(ByVal value As Boolean)
            mCanBeFolder = value
        End Set
    End Property
    Dim mIsFolder As Boolean
    ''' <summary>
    ''' 是否在折叠状态
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsFolder() As Boolean
        Get
            Return mIsFolder
        End Get
        Set(ByVal value As Boolean)
            mIsFolder = value
        End Set
    End Property
    Dim mIsCommentLine As Boolean
    ''' <summary>
    '''  该行是否为整行注释行
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsCommentLine() As Boolean
        Get
            Return mIsCommentLine
        End Get
        Set(ByVal value As Boolean)
            mIsCommentLine = value
        End Set
    End Property
    Dim mIsCommentStart As Boolean
    ''' <summary>
    ''' 该行是否为一个注释快的头部
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsCommentStart() As Boolean
        Get
            Return mIsCommentStart
        End Get
        Set(ByVal value As Boolean)
            mIsCommentStart = value
        End Set
    End Property
    Dim mIsCommentEnd As Boolean
    ''' <summary>
    ''' 该行是否为一个注释快的尾部
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsCommentEnd() As Boolean
        Get
            Return mIsCommentEnd
        End Get
        Set(ByVal value As Boolean)
            mIsCommentEnd = value
        End Set
    End Property
    Dim mIsHidden As Boolean
    ''' <summary>
    ''' 该行是否为隐藏行
    ''' </summary>
    ''' <remarks></remarks>
    Property Real_IsHidden() As Boolean
        Get
            Return mIsHidden
        End Get
        Set(ByVal value As Boolean)
            mIsHidden = value
        End Set
    End Property
#End Region
End Class
